﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;

namespace Wpf.Explorations.TestApplication
{
	/// <summary>
	/// Person view model.
	/// </summary>
	public sealed class PersonViewModel : INotifyPropertyChanged
	{
		#region Private Static Variables 
		private static readonly ObservableCollection<PersonViewModel> _people = PersonViewModel.CreatePeople();
		#endregion Private Static Variables 

		#region Public Static Properties 
		/// <summary>
		/// Gets the people.
		/// </summary>
		/// <value>The people.</value>
		public static ObservableCollection<PersonViewModel> People
		{
			get
			{
				return PersonViewModel._people;
			}
		}
		#endregion Public Static Properties 

		#region Private Static Methods 
		/// <summary>
		/// Creates the people.
		/// </summary>
		/// <returns>
		/// Observable collection.
		/// </returns>
		private static ObservableCollection<PersonViewModel> CreatePeople()
		{
			KeyValuePair<Gender, string>[] firstNames = new[]
			{
				new KeyValuePair<Gender, string>(Gender.Male, "Alex"),
				new KeyValuePair<Gender, string>(Gender.Male, "Charles"),
				new KeyValuePair<Gender, string>(Gender.Male, "Robert"),
				new KeyValuePair<Gender, string>(Gender.Male, "William"),
				new KeyValuePair<Gender, string>(Gender.Male, "Stephen"),
				new KeyValuePair<Gender, string>(Gender.Male, "Richard"),
				new KeyValuePair<Gender, string>(Gender.Female, "Wendy"),
				new KeyValuePair<Gender, string>(Gender.Female, "Stacy"),
				new KeyValuePair<Gender, string>(Gender.Female, "Dani"),
				new KeyValuePair<Gender, string>(Gender.Female, "Jenna"),
				new KeyValuePair<Gender, string>(Gender.Female, "Alice"),
				new KeyValuePair<Gender, string>(Gender.Female, "Susan")
			};
			string[] lastNames = new[]
			{
				"Smith",
				"Gold",
				"Murphy",
				"Sanchez",
				"Patel",
				"Gray",
				"Wong",
				"White"
			};
			Random random = new Random((Guid.NewGuid().ToByteArray()[0] << 2) + Guid.NewGuid().ToByteArray()[0]);
			ObservableCollection<PersonViewModel> people = new ObservableCollection<PersonViewModel>();
			for (int i = 0; i < 6; i++)
			{
				int firstNameIndex;
				people.Add(new PersonViewModel
				{
					FirstName = firstNames[firstNameIndex = random.Next(0, firstNames.Length)].Value,
					LastName = lastNames[random.Next(0, lastNames.Length)],
					Gender = firstNames[firstNameIndex].Key,
					Age = random.Next(0, 99)
				});
			}
			return people;
		}
		#endregion Private Static Methods 

		#region Private Variables 
		private Gender _gender;
		private int _age;
		#endregion Private Variables 

		#region Public Properties 
		/// <summary>
		/// Gets or sets the age.
		/// </summary>
		/// <value>The age.</value>
		public int Age
		{
			get
			{
				return this._age;
			}
			set
			{
				if (this._age != value)
				{
					Category category = this.Category;
					this._age = value;
					this.OnPropertyChanged("Age");
					if (this.Category != category)
					{
						this.OnPropertyChanged("Category");
					}
				}
			}
		}

		/// <summary>
		/// Gets the category.
		/// </summary>
		/// <value>The category.</value>
		public Category Category
		{
			get
			{
				if (this._age <= 12)
				{
					return Category.Child;
				}
				if (this._age <= 18)
				{
					return Category.Adolescent;
				}
				if (this._age < 65)
				{
					return Category.Adult;
				}
				return Category.SeniorCitizen;
			}
		}

		/// <summary>
		/// Gets or sets the first name.
		/// </summary>
		/// <value>The first name.</value>
		public string FirstName
		{
			get;
			private set;
		}

		/// <summary>
		/// Gets or sets the gender.
		/// </summary>
		/// <value>The gender.</value>
		public Gender Gender
		{
			get
			{
				return this._gender;
			}
			set
			{
				if (this._gender != value)
				{
					this._gender = value;
					this.OnPropertyChanged("Gender");
				}
			}
		}

		/// <summary>
		/// Gets or sets the last name.
		/// </summary>
		/// <value>The last name.</value>
		public string LastName
		{
			get;
			private set;
		}
		#endregion Public Properties 

		#region Private Methods 
		/// <summary>
		/// Raises the 'PropertyChanged' event.
		/// </summary>
		/// <param name="propertyName">Name of the property.</param>
		private void OnPropertyChanged(string propertyName)
		{
			if (this.PropertyChanged != null)
			{
				this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
			}
		}
		#endregion Private Methods 

		#region Public Events 
		/// <summary>
		/// Occurs when a property value changes.
		/// </summary>
		public event PropertyChangedEventHandler PropertyChanged;
		#endregion Public Events 
	}
}